﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using InstantMessenger.Transports;
using System.Linq;

namespace InstantMessenger
{
    public partial class MessageForm : Form
    {
        private readonly Contact owningContact;
        private readonly ContextMenu sendButtonContextMenu;
        private Contact selectedFriend;
        private bool isClosing;

        public MessageForm(Contact owningContact)
        {
            this.owningContact = owningContact;

            InitializeComponent();

            Text = owningContact.Name;

            sendButtonContextMenu = new ContextMenu();
            sendButton.ShowSplit = true;
            sendButton.SplitMenu = sendButtonContextMenu;

            AddFriends();

            foreach (var contact in owningContact.Friends)
                contact.PropertyChanged += contact_PropertyChanged;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            messageText.Focus();
        }

        private void contact_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Transport")
            {
                InvokeOnUiThread(() =>
                                     {
                                         var contact = (Contact) sender;
                                         var menuItem = sendButtonContextMenu.MenuItems.Cast<MenuItem>().FirstOrDefault(x => x.Tag == sender);
                                         if (menuItem != null)
                                         {
                                             menuItem.Enabled = contact.IsOnline;
                                             menuItem.Text = contact.ToString();
                                         }
                                     });
            }
        }

        private void InvokeOnUiThread(Action action)
        {
            if (InvokeRequired)
                Invoke(action);
            else
                action();
        }

        private void AddFriends()
        {
            foreach (var contact in owningContact.Friends.OrderBy(x => x.Name))
            {
                var item = new MenuItem { Enabled = contact.IsOnline, Tag = contact, Text = contact.ToString() };
                item.Click += (sender, eventArgs) =>
                                  {
                                      selectedFriend = ((Contact) ((MenuItem) sender).Tag);
                                      sendButton.Text = string.Format("Send to {0}", selectedFriend.Name);
                                  };
                sendButtonContextMenu.MenuItems.Add(item);
            }
        }

        public void ReceiveMessage(string sender, string message)
        {
            InvokeOnUiThread(() => AppendText(string.Format("{0}: {1}{2}", sender, message, Environment.NewLine)));
        }

        private void SendMessage()
        {
            if (selectedFriend != null && !string.IsNullOrEmpty(messageText.Text))
            {
                if (selectedFriend.DeliverMessage(owningContact, messageText.Text))
                {
                    InvokeOnUiThread(() =>
                                         {
                                             this.messageHistoryText.
                                             AppendText(string.Format("me (to {2}): {0}{1}", messageText.Text, Environment.NewLine, selectedFriend.Name));
                                             messageText.Clear();
                                         });
                }
            }
        }

        private void AppendText(string text)
        {
            messageHistoryText.AppendText(text);
        }

        private void sendButton_Click(object sender, EventArgs e)
        {
            SendMessage();
        }

        private void MessageForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!isClosing)
            {
                isClosing = true;
                owningContact.ReplaceTransport(new OfflineTransport());
                isClosing = false;
            }
        }

        public void TransportEnded()
        {
            InvokeOnUiThread(Close);
        }
    }
}
